package com.zhuoyue.biz.core.api.service.impl;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhuoyue.biz.core.api.dao.*;
import com.zhuoyue.biz.core.api.domain.*;
import com.zhuoyue.biz.core.api.dto.rep.GatewayRepDTO;
import com.zhuoyue.common.exception.ErrorType;
import com.zhuoyue.common.exception.ZyServerException;
import com.zhuoyue.common.utils.CmdUtils;
import com.zhuoyue.common.utils.Time;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;

import com.zhuoyue.biz.core.api.service.GatewayService;


/**
 * @author wjming
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class GatewayServiceImpl extends ServiceImpl<GatewayDao, GatewayDO> implements GatewayService {

    private final GatewayDao gatewayDao;
    private final DeviceDao deviceDao;
    private final GroupMapper groupMapper;
    private final AutomateDao automateDao;
    private final LocalSceneDao localSceneDao;
    private final ProductInfoAppService productInfoAppService;

    private static final int GATEWAY_MAC_SIZE = 7;
    private static final String GATEWAY_BOJING = "gateway_bojing";

    @Override
    public GatewayRepDTO addGateway(GatewayDO gateway) {
        GatewayRepDTO gatewayRepDTO = new GatewayRepDTO();
        List<GatewayDO> gatewayList = gatewayDao.selectList(Wrappers.<GatewayDO>lambdaQuery()
                .like(GatewayDO::getZigbeeMac, gateway.getZigbeeMac()));
        gateway.setGatewayPush("1");
        if (CollectionUtils.isNotEmpty(gatewayList)) {
            if (gatewayList.get(0).getHomeId() != null) {
                throw new ZyServerException(ErrorType.INVALID_PARAMS.getCode(), "网关已绑定家庭，请先解绑！");
            }
            gateway.setId(gatewayList.get(0).getId());

            GatewayDO gatewayDO = updateGatewayById(gateway);
            List<String> deviceFun = productInfoAppService.getDeviceFun(gatewayDO.getProdId());
            gatewayRepDTO.gatewayDoToDto(gatewayDO, deviceFun);
            Group group = Group.builder().homeId(gateway.getHomeId()).build();
            AutomateDO automateDO = AutomateDO.builder().homeId(gateway.getHomeId()).build();
            LocalSceneDO localSceneDO = LocalSceneDO.builder().homeId(gateway.getHomeId()).build();

            groupMapper.update(group, Wrappers.<Group>lambdaQuery().eq(Group::getGatewayMac, gateway.getZigbeeMac()));
            automateDao.update(automateDO, Wrappers.<AutomateDO>lambdaQuery().eq(AutomateDO::getGatewayMac, gateway.getZigbeeMac()));
            localSceneDao.update(localSceneDO, Wrappers.<LocalSceneDO>lambdaQuery().eq(LocalSceneDO::getGatewayMac, gateway.getZigbeeMac()));
            return gatewayRepDTO;
        } else {
            if (gateway.getZigbeeMac().length() < GATEWAY_MAC_SIZE) {
                throw new ZyServerException(ErrorType.Service_Fail.getCode(), "铂金网关新增失败请网关检查是否已连上网络");
            }
            int count = gatewayDao.insert(gateway);
            if (count < 1) {
                throw new ZyServerException(ErrorType.Service_Fail.getCode(), "网关新增失败");
            }

            String zigbeeMac = gatewayDao.selectById(gateway.getId()).getZigbeeMac();
            Group group = Group.builder().homeId(gateway.getHomeId()).build();
            AutomateDO automateDO = AutomateDO.builder().homeId(gateway.getHomeId()).build();
            LocalSceneDO localSceneDO = LocalSceneDO.builder().homeId(gateway.getHomeId()).build();
            gateway.setZigbeeMac(zigbeeMac);
            groupMapper.update(group, Wrappers.<Group>lambdaQuery().eq(Group::getGatewayMac, gateway.getZigbeeMac()));
            automateDao.update(automateDO, Wrappers.<AutomateDO>lambdaQuery().eq(AutomateDO::getGatewayMac, gateway.getZigbeeMac()));
            localSceneDao.update(localSceneDO, Wrappers.<LocalSceneDO>lambdaQuery().eq(LocalSceneDO::getGatewayMac, gateway.getZigbeeMac()));
        }

        GatewayDO gwRes = gatewayDao.selectById(gateway.getId());
        List<String> deviceFun = productInfoAppService.getDeviceFun(gwRes.getProdId());
        gatewayRepDTO.gatewayDoToDto(gwRes, deviceFun);
        return gatewayRepDTO;
    }

    @Override
    public GatewayDO updateGatewayById(GatewayDO gateway) {
        int count = gatewayDao.update(gateway, Wrappers.<GatewayDO>lambdaQuery()
                .eq(GatewayDO::getId, gateway.getId()));
        if (count < 1) {
            throw new ZyServerException(ErrorType.OBJECT_NOT_FOUND.getCode(), "网关修改失败！");
        }
        if (null != gateway && StringUtils.isNotEmpty(gateway.getZigbeeMac()) && gateway.getZigbeeMac().length() <= GATEWAY_MAC_SIZE) {
            gateway = gatewayDao.selectGatewayById(gateway.getId());
        }

        return gatewayDao.selectOne(Wrappers.<GatewayDO>lambdaQuery().eq(GatewayDO::getId, gateway.getId()));
    }

    @Override
    public Boolean deleteGatewayById(String gatewayId) {
        //判断如果是铂金网关
        GatewayDO gatewayDO = gatewayDao.selectById(gatewayId);
        //铂晶版本的网关
        if (StringUtils.isNotEmpty(gatewayDO.getImgUrl()) && GATEWAY_BOJING.equals(gatewayDO.getImgUrl())) {
            //清空他的homeId
            GatewayDO gatewayDo = new GatewayDO();
            gatewayDo.setId(gatewayId);
            gatewayDo.setHomeId("");
            gatewayDao.updateGatewaySelective(gatewayDo);
        } else {
            try {
                gatewayDao.deleteById(gatewayId);
            } catch (Exception e) {
                if (e instanceof DataIntegrityViolationException) {
                    throw new ZyServerException(ErrorType.OBJECT_NOT_FOUND.getCode(), "网关下存在设备无法删除");
                }
            }
        }
        return true;
    }

    /**
     * 这步操作应当先查询一下这个家庭下有无场景
     *
     * @param gatewayId
     */
    @Override
    public void unbindGatewayById(String gatewayId) {
        GatewayDO gateway = new GatewayDO();
        gateway.setId(gatewayId);
        gateway.setHomeId("-1");
        int count = gatewayDao.updateGatewaySelective(gateway);
        if (count < 1) {
            throw new ZyServerException(ErrorType.OBJECT_NOT_FOUND.getCode(), "解除网关失败！");
        }
        DeviceDO device = new DeviceDO();
        device.setGatewayId(gatewayId);
        device.setRoomId("-1");
        deviceDao.updateDeviceByGatewayId(device);

        //解绑场景，自动化，群组

        Group group = Group.builder().homeId("-1").build();
        AutomateDO automateDO = AutomateDO.builder().homeId("-1").build();
        LocalSceneDO localSceneDO = LocalSceneDO.builder().homeId("-1").build();
        String gatewayMac = gatewayDao.selectById(gatewayId).getZigbeeMac();
        gateway.setZigbeeMac(gatewayMac);
        groupMapper.update(group, Wrappers.<Group>lambdaQuery().eq(Group::getGatewayMac, gateway.getZigbeeMac()));
        automateDao.update(automateDO, Wrappers.<AutomateDO>lambdaQuery().eq(AutomateDO::getGatewayMac, gateway.getZigbeeMac()));
        localSceneDao.update(localSceneDO, Wrappers.<LocalSceneDO>lambdaQuery().eq(LocalSceneDO::getGatewayMac, gateway.getZigbeeMac()));


    }

    @Override
    public GatewayDO getByHomeId(String homeId) {
        GatewayDO gatewayDO = gatewayDao.selectOne(Wrappers.<GatewayDO>lambdaQuery()
                .eq(GatewayDO::getHomeId, homeId));
        return gatewayDO;
    }

    @Override
    public String clearGatewayFrame(String gatewayMac) {
        String frameStr = "0200" + gatewayMac + "13B0050101";
        frameStr = "2A" + CmdUtils.getDateLength(frameStr) + frameStr + CmdUtils.getCmdBodySum(frameStr) + "23";
        return frameStr;
    }

    @Override
    public String resetGatewayFrame(String gatewayMac) {
        String frameStr = "0200" + gatewayMac + "13B0070101";
        frameStr = "2A" + CmdUtils.getDateLength(frameStr) + frameStr + CmdUtils.getCmdBodySum(frameStr) + "23";
        return frameStr;
    }

    @Override
    public List<GatewayRepDTO> getGatewayMessages(String homeId) {
        List<GatewayDO> list = list(Wrappers.<GatewayDO>lambdaQuery().eq(GatewayDO::getHomeId, homeId)
                .orderByAsc(GatewayDO::getCreateTime));
        List<GatewayRepDTO> gatewayReptos = new ArrayList<>();
        list.stream().forEach(gatewayDO -> {
            List<String> deviceFun = productInfoAppService.getDeviceFun(gatewayDO.getProdId());
            GatewayRepDTO gatewayRepDTO = new GatewayRepDTO().gatewayDoToDto(gatewayDO, deviceFun);
            gatewayReptos.add(gatewayRepDTO);
        });
        return gatewayReptos;
    }
}
